﻿using System;
using System.Globalization;
using System.Text;
using Luna.Connectors;
using Luna.Data;
using Luna.Data.Configuration;
using Rhino.Mocks;

namespace Luna.Services.Test
{
    public class DataCreator
    {
        public static readonly DateTime BASEDATE = new DateTime(3000, 1, 1);

        protected const string AUDIT_COMMENT = "Unit test";

        protected const string TEST_PREFIX = "#Test";

        private const string PREFIX_FORMAT = "{0}_{1}_";

        public DataCreator()
        {
            Randomizer = new Random();
        }

        protected Random Randomizer { get; private set; }

        public IReferenceData CreateReferenceData()
        {
            IReferenceData L_Return = MockRepository.GenerateMock<object, IReferenceData, IEquatable<object>>() as IReferenceData;
            LoadReferenceData(L_Return);

            return L_Return;
        }

        public bool GetBool()
        {
            return GetInt() % 2 == 0;
        }

        public byte[] GetByteArray()
        {
            byte[] L_Return = new byte[GetInt()];
            Randomizer.NextBytes(L_Return);

            return L_Return;
        }

        public DateTime GetDate()
        {
            return BASEDATE.AddDays(Randomizer.Next(50000));
        }

        public decimal GetDecimal()
        {
            return Convert.ToDecimal(GetInt());
        }

        public double GetDouble()
        {
            return Randomizer.NextDouble() * 5000;
        }

        public T GetEnum<T>()
        {
            var L_Values = Enum.GetValues(typeof(T));
            return (T)L_Values.GetValue(Randomizer.Next(L_Values.Length - 1));
        }

        public int GetInt()
        {
            return Randomizer.Next(5000);
        }

        public DateTime? GetNullableDate()
        {
            return GetBool() ? (DateTime?)GetDate() : null;
        }

        public int? GetNullableInt()
        {
            return GetBool() ? (int?)GetInt() : null;
        }

        public string GetString()
        {
            return GetString(string.Empty);
        }

        public string GetString(int P_Size)
        {
            StringBuilder L_Builder = new StringBuilder();
            for (int i = 0; i < P_Size; i++)
            {
                L_Builder.Append(Randomizer.Next(9));
            }

            return L_Builder.ToString();
        }

        public string GetString(string P_Format)
        {
            return string.Format(CultureInfo.InvariantCulture, PREFIX_FORMAT + P_Format, TEST_PREFIX, GetInt());
        }

        public void SetUp(IDataContext P_Context)
        {
            P_Context.Stub(x => x.Create<IReferenceData>()).Return(CreateReferenceData());
        }

        protected string GetString(string P_Name, int P_CharCount)
        {
            return GetString(P_Name).Substring(0, P_CharCount);
        }

        protected void LoadKey(ILunaData P_Data)
        {
            P_Data.Stub(x => x.PK).PropertyBehavior();
            P_Data.Stub(x => x.AlreadyPersisted).PropertyBehavior();
            P_Data.AlreadyPersisted = false;

            P_Data.PK = Guid.NewGuid();

            P_Data.Stub(x => x.Equals(Arg<object>.Is.Anything)).WhenCalled(x => x.ReturnValue = CheckTrue(x.Arguments[0], P_Data)).Return(true);
        }

        protected void LoadReferenceData(IReferenceData P_Data)
        {
            P_Data.Stub(x => x.PK).PropertyBehavior();
            P_Data.PK = Guid.NewGuid();

            P_Data.Stub(x => x.AlreadyPersisted).PropertyBehavior();
            P_Data.Stub(x => x.From).PropertyBehavior();
            P_Data.Stub(x => x.Google).PropertyBehavior();
            P_Data.Stub(x => x.GoogleLastUpdate).PropertyBehavior();
            P_Data.Stub(x => x.LastUpdate).PropertyBehavior();
            P_Data.Stub(x => x.ZohoCRM).PropertyBehavior();
            P_Data.Stub(x => x.ZohoCRMLastUpdate).PropertyBehavior();

            P_Data.From = GetEnum<ConnectorType>();
            P_Data.AlreadyPersisted = false;
            P_Data.Google = GetString(32);
            P_Data.GoogleLastUpdate = GetNullableDate();
            P_Data.LastUpdate = GetNullableDate();
            P_Data.Validated = GetBool();
            P_Data.ZohoCRM = GetNullableInt();
            P_Data.ZohoCRMLastUpdate = GetNullableDate();

            P_Data.Stub(x => x.Equals(Arg<object>.Is.Anything)).WhenCalled(x => x.ReturnValue = CheckTrue(x.Arguments[0], P_Data)).Return(true);
        }

        private static bool CheckTrue(object a, IReferenceData res)
        {
            return (a is IReferenceData) && ((IReferenceData)a).PK == res.PK;
        }

        private static bool CheckTrue(object a, ILunaData res)
        {
            return (a is ILunaData) && ((ILunaData)a).PK == res.PK;
        }
    }
}